package com.yungu.swift.order.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.google.common.collect.Lists;
import com.yungu.swift.assets.driver.model.dto.DriverHeatMapDto;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.mapper.IMapper;
import com.yungu.swift.base.model.admin.AdminUuidParam;
import com.yungu.swift.base.service.impl.BaseServiceImpl;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.constants.OrderConstant;
import com.yungu.swift.lbs.model.Coordinate;
import com.yungu.swift.lbs.model.DriverLocation;
import com.yungu.swift.lbs.model.param.TrsearchParam;
import com.yungu.swift.lbs.model.vo.OrderLocationVo;
import com.yungu.swift.lbs.model.vo.TrackVo;
import com.yungu.swift.lbs.service.DistanceService;
import com.yungu.swift.lbs.service.LocationService;
import com.yungu.swift.order.config.ApplicationConfig;
import com.yungu.swift.order.dao.OrderDetailMapper;
import com.yungu.swift.order.model.dto.OrderDetailDto;
import com.yungu.swift.order.model.dto.OrderOperateLogDto;
import com.yungu.swift.order.model.vo.AdminGeneralOrderDetailVo;
import com.yungu.swift.order.service.OrderDetailService;
import com.yungu.swift.order.service.OrderOperateLogService;
import com.yungu.swift.order.utils.PolylineUtils;
import com.yungu.swift.system.finance.model.dto.FinanceJoinRefundDto;
import com.yungu.swift.system.finance.service.FinanceJoinRefundService;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * OrderDetailServiceImpl
 **/
@Slf4j
@Service
public class OrderDetailServiceImpl extends BaseServiceImpl<OrderDetailDto> implements OrderDetailService {

    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderOperateLogService orderOperateLogService;
    @Reference
    private LocationService locationService;
    @Reference
    private DistanceService distanceService;
    @Reference
    private FinanceJoinRefundService financeJoinRefundService;

    @Override
    protected IMapper<OrderDetailDto> getMapper() {
        return orderDetailMapper;
    }

    @Override
    public ResponseData<Boolean> littleWords(String orderUuid, String content) {
        Map<String, Object> map = MapUtils.build(2);
        map.put("orderUuid", orderUuid);
        OrderDetailDto orderDetailDto = getMapper().list(map).get(0);
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "查无订单详情数据");
        }
        orderDetailDto.setRemark(content);
        orderDetailDto.setUpdateOn(new Date());
        this.add(orderDetailDto);
        return ResponseData.buildSuccessResponse("捎话成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<AdminGeneralOrderDetailVo> getGeneralOrderDetail(AdminUuidParam adminUuidParam) {
        AdminGeneralOrderDetailVo orderDetailVo = orderDetailMapper.getGeneralOrderDetail(adminUuidParam.getUuid());
        if (orderDetailVo != null) {
            // 其他费用
            Integer othersFare = 0;
            if (orderDetailVo.getHighwayFare() != null) {
                othersFare += orderDetailVo.getHighwayFare();
            }
            if (orderDetailVo.getRoadBridgeFare() != null) {
                othersFare += orderDetailVo.getRoadBridgeFare();
            }
            if (orderDetailVo.getOtherFare() != null) {
                othersFare += orderDetailVo.getOtherFare();
            }
            orderDetailVo.setOthersFare(othersFare);
            //改派和调价纪录
            List<OrderOperateLogDto> dataList = orderOperateLogService.listReassignAndAdjust(adminUuidParam.getUuid()).getData();
            if (CollectionUtils.isNotEmpty(dataList)) {
                List<OrderOperateLogDto> reassignList = new ArrayList<>();
                List<OrderOperateLogDto> adjustList = new ArrayList<>();
                for (OrderOperateLogDto orderOperateLogDto : dataList) {
                    if (OrderOperateLogDto.TYPE_ASS == orderOperateLogDto.getType()) {
                        reassignList.add(orderOperateLogDto);
                    }
                    if (OrderOperateLogDto.TYPE_ADJUST == orderOperateLogDto.getType()) {
                        adjustList.add(orderOperateLogDto);
                    }
                }
                if (reassignList.size() > 0) {
                    orderDetailVo.setReassignList(reassignList);
                }
                if (adjustList.size() > 0) {
                    orderDetailVo.setAdjustList(adjustList);
                }
            }
            // 订单轨迹点
            Integer typeModule = orderDetailVo.getTypeModule();
            if (typeModule == CommonConstant.BUSINESS_TYPE_POOL || typeModule == CommonConstant.BUSINESS_TYPE_PARCEL) {
                joinTrackPointList(orderDetailVo);
            } else {
                trackPointList(orderDetailVo);
            }
            //取出预估轨迹点 解析成集合
            if (StringUtils.isNotEmpty(orderDetailVo.getPlanRoute())) {
                try {
                    orderDetailVo.setPlanRouteList(PolylineUtils.decodePoly(orderDetailVo.getPlanRoute()));
                    orderDetailVo.setPlanRoute(null);
                } catch (Exception e) {
                    log.info("订单{}取出预估轨迹点异常", orderDetailVo.getOrderUuid());
                }

            }
        }
        return ResponseData.buildSuccessResponse(orderDetailVo);
    }

    private void joinTrackPointList(AdminGeneralOrderDetailVo orderDetailVo) {
        List<DriverLocation> driverLocations = locationService.findOrderMapPoint(orderDetailVo.getOrderUuid(),
                orderDetailVo.getAppid()).getData();
        if (CollectionUtils.isNotEmpty(driverLocations)) {
            List<DriverLocation> wayPoints = new ArrayList<>();
            for (DriverLocation driverLocation : driverLocations) {
                if ("CKSC".equals(driverLocation.getPositionType())) {
                    orderDetailVo.setPickUpPoint(convertLocationVo(driverLocation));
                }
                wayPoints.add(driverLocation);
            }
            orderDetailVo.setGetOffPoint(convertLocationVo(wayPoints.get(wayPoints.size() - 1)));
            orderDetailVo.setWayPoints(wayPoints);
        }
        if (null != orderDetailVo && 1 == orderDetailVo.getCloseStatus()) {
            FinanceJoinRefundDto financeRefundDto = financeJoinRefundService.queryByOrderUuid(orderDetailVo.getOrderUuid()).getData();
            orderDetailVo.setFinanceJoinRefundDto(financeRefundDto);
        }
    }


    private void trackPointList(AdminGeneralOrderDetailVo orderDetailVo) {
        //计费轨迹
        List<OrderLocationVo> billingPoints = new ArrayList<>();
        //司机去接乘客轨迹
        List<OrderLocationVo> pickUpPassengerPoints = new ArrayList<>();
        //乘客下车到司机确认费用轨迹
        List<OrderLocationVo> endOrderPoints = new ArrayList<>();

        List<DriverLocation> driverLocations = locationService.findOrderMapPoint(orderDetailVo.getOrderUuid(),
                orderDetailVo.getAppid()).getData();

        // 是否开启里程纠偏 开启时 从高德获取订单计费轨迹 否则从mongodb获取
        if (ApplicationConfig.SERVER_CONFIG.getSystem().getTurnOnCorrection()) {
            billingPoints = locationsCheck(orderDetailVo.getAppid(), orderDetailVo.getOrderUuid(), orderDetailVo.getDriverUuid());
            orderDetailVo.setBillingPoints(billingPoints);
        }
        if (CollectionUtils.isNotEmpty(driverLocations)) {
            for (DriverLocation driverLocation : driverLocations) {
                //司机接单
                if ("DDPD".equals(driverLocation.getPositionType())) {
                    orderDetailVo.setTakeOrderPoint(convertLocationVo(driverLocation));
                }
                //司机出发
                if ("SJCF".equals(driverLocation.getPositionType())) {
                    orderDetailVo.setDriverDeparPoint(convertLocationVo(driverLocation));
                }
                //乘客上车
                if ("CKSC".equals(driverLocation.getPositionType())) {
                    orderDetailVo.setPickUpPoint(convertLocationVo(driverLocation));
                }
                //乘客下车
                if ("CKXC".equals(driverLocation.getPositionType())) {
                    orderDetailVo.setGetOffPoint(convertLocationVo(driverLocation));
                }
                //司机取消
                if ("SJQX".equals(driverLocation.getPositionType())) {
                    orderDetailVo.setDriverCancelPoint(convertLocationVo(driverLocation));
                }
                //乘客取消
                if ("CKQX".equals(driverLocation.getPositionType())) {
                    orderDetailVo.setPassengerCancelPoint(convertLocationVo(driverLocation));
                }
                //司机出发到乘客上车轨迹
                if (driverLocation.getOrderStatus() != null && driverLocation.getOrderStatus() >= OrderConstant.ORDER_STATUS_GO
                        && driverLocation.getOrderStatus() < OrderConstant.ORDER_STATUS_START) {
                    pickUpPassengerPoints.add(convertLocationVo(driverLocation));
                }
                //乘客下车到司机确认费用轨迹
                if (driverLocation.getOrderStatus() != null && driverLocation.getOrderStatus() >= OrderConstant.ORDER_STATUS_ARRIVED) {
                    //存乘客上车前的定位点 拼接纠偏后的定位点
                    endOrderPoints.add(convertLocationVo(driverLocation));
                }
                //若纠偏未开启 或者高德查询不到位置点信息 则从Mongodb获取
                if (CollectionUtils.isEmpty(orderDetailVo.getBillingPoints()) && driverLocation.getOrderStatus() != null
                        && driverLocation.getOrderStatus() >= OrderConstant.ORDER_STATUS_START
                        && driverLocation.getOrderStatus() < OrderConstant.ORDER_STATUS_ARRIVED) {
                    billingPoints.add(convertLocationVo(driverLocation));
                }
            }
            //如果订单已确认费用 则轨迹最后一个点为确认费用点
            if (Integer.parseInt(orderDetailVo.getSubStatus()) >= OrderConstant.ORDER_STATUS_FARE_CONFIRM) {
                orderDetailVo.setConfirmFarePoint(convertLocationVo(driverLocations.get(driverLocations.size() - 1)));
            }

        }
        orderDetailVo.setPickUpPassengerPoints(pickUpPassengerPoints);
        orderDetailVo.setBillingPoints(billingPoints);
        orderDetailVo.setEndOrderPoints(endOrderPoints);
    }

    /**
     * 将轨迹调用鹰眼接口进行纠偏
     *
     * @return
     */
    private List<OrderLocationVo> locationsCheck(String appid, String uuid, String driverUuid) {
        ResponseData<List<TrackVo>> listResponseData = distanceService.gaodeTraceCheck(driverUuid, uuid, new TrsearchParam());
        if (listResponseData.isSuccess() && CollectionUtils.isNotEmpty(listResponseData.getData())) {
            TrackVo trackVo = listResponseData.getData().get(0);
            List<OrderLocationVo> collect = trackVo.getPoints().stream().map(point -> {
                String location = point.getLocation();
                String[] split = location.split("\\,");
                OrderLocationVo orderLocationVo = new OrderLocationVo();
                Coordinate coordinate = new Coordinate();
                orderLocationVo.setLng(Double.parseDouble(split[0]));
                orderLocationVo.setLat(Double.parseDouble(split[1]));
                return orderLocationVo;
            }).collect(Collectors.toList());
            log.info("------------------订单id:{} 进行猎鹰轨迹纠偏成功,定位点个数：{}", uuid, collect.size());
            return collect;

        }
        return Lists.newArrayList();
    }


    @Override
    public ResponseData<OrderDetailDto> saveOrUpdate(OrderDetailDto orderDetailDto) {
        int complete;
        if (StringUtils.isNotBlank(orderDetailDto.getUuid())) {
            orderDetailDto.setUpdateOn(new Date());
            complete = orderDetailMapper.edit(orderDetailDto);
        } else {
            orderDetailDto.setUuid(StringUtils.buildUUID());
            orderDetailDto.setCreateOn(new Date());
            complete = orderDetailMapper.add(orderDetailDto);
        }
        if (complete > 0) {
            return ResponseData.buildSuccessResponse(orderDetailDto);
        }
        return ResponseData.buildSuccessResponse(null);
    }


    @Override
    public ResponseData<List<DriverHeatMapDto>> heapMapOrderStatis(Integer type, Integer time) {
        return ResponseData.buildSuccessResponse(orderDetailMapper.listHeatMapOrder(type, time));
    }

    /**
     * 转换位置点返回值
     *
     * @param driverLocation
     * @return
     */
    private OrderLocationVo convertLocationVo(DriverLocation driverLocation) {
        OrderLocationVo orderLocationVo = new OrderLocationVo();
        orderLocationVo.setUploadTime(driverLocation.getUploadTime().getTime());
        Coordinate coordinate = driverLocation.getCoordinate();
        orderLocationVo.setLat(coordinate.getLat());
        orderLocationVo.setLng(coordinate.getLng());
        return orderLocationVo;
    }
}